﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using WallpaperSharing.DataAccess.Interfaces;
using WallpaperSharing.Domain;
using WallpaperSharing.DataAccess;

namespace WallpaperSharing.AppLibrary.Forms
{

    public partial class BrowserForm : Form
    {
        private const string DEFAULT_FILE_NAME = "*";
        private static readonly string SAVE_FILE_DIALOG_FILTERS;
        private static readonly IList<string> AVAILABLE_FILE_EXTENSIONS;
        private static readonly IList<Size> AVAILABLE_THUMBNAILS_SIZES; 
        private static readonly Color THUMBNAIL_BACK_COLOR = Color.FromArgb(255, 255, 255);
        private static readonly Color SELECTED_THUMBNAIL_BACK_COLOR = Color.FromArgb(150, 255, 100);
        private static readonly Padding THUMBNAIL_FRAME_SIZE = new Padding(3);

        private readonly IWallpaperDao _wallpaperDao;
        private readonly ICategoryDao _categoryDao;
        private readonly SaveFileDialog _saveFileDialog;

        private PictureBox _selectedPictureBox;
        private PictureBox SelectedPictureBox
        {
            get { return _selectedPictureBox; }
            set
            {
                _selectedPictureBox = value;
                btnSave.Enabled = _selectedPictureBox != null;
            }
        }
        private Size _thumbnailsSize;
        private int _selectedCategoryId;


        static BrowserForm()
        {
            AVAILABLE_FILE_EXTENSIONS = ConfigureFileExtensions();
            SAVE_FILE_DIALOG_FILTERS = ConfigureSaveFileDialogFormat(AVAILABLE_FILE_EXTENSIONS);

            AVAILABLE_THUMBNAILS_SIZES = ConfigureThumbnailsSizes();
        }

        private static IList<string> ConfigureFileExtensions()
        {
            return new List<string>
            {
                ".jpg",
                ".jpeg",
                ".png",
                ".gif",
                ".bmp",
                ".tiff"
            };
        }

        private static string ConfigureSaveFileDialogFormat(IEnumerable<string> formats)
        {
            var nameBuilder = new StringBuilder("Image files (");
            var filterBuilder = new StringBuilder("|");
            const string nameDelimiter = ", ";
            const string filterDelimiter = ";";
            const string prefix = "*";
            foreach (var fileExtension in formats)
            {
                nameBuilder.Append(prefix);
                nameBuilder.Append(fileExtension);
                nameBuilder.Append(nameDelimiter);

                filterBuilder.Append(prefix);
                filterBuilder.Append(fileExtension);
                filterBuilder.Append(filterDelimiter);
            }
            if (AVAILABLE_FILE_EXTENSIONS.Count > 0)
            {
                nameBuilder.Length -= nameDelimiter.Length;
                filterBuilder.Length -= filterDelimiter.Length;
            }
            nameBuilder.Append(")");
            return nameBuilder.ToString() + filterBuilder;
        }

        private static IList<Size> ConfigureThumbnailsSizes()
        {
            return new List<Size>
            {
                new Size { Width = 30, Height = 30 },
                new Size { Width = 50, Height = 50 },
                new Size { Width = 80, Height = 80 },
                new Size { Width = 120, Height = 120 },
                new Size { Width = 160, Height = 160 }
            };
        }


        public BrowserForm()
        {
            _wallpaperDao = new WallpaperDao();
            _categoryDao = new CategoryDao();
            InitializeComponent();

            _saveFileDialog = new SaveFileDialog
            {
                DefaultExt = AVAILABLE_FILE_EXTENSIONS[0].Substring(1),
                ValidateNames = true,
                Filter = SAVE_FILE_DIALOG_FILTERS
            };
            _thumbnailsSize = AVAILABLE_THUMBNAILS_SIZES[0];

            LoadCategories();
        }


        private void AddThumbnailsToPanel(IEnumerable<Wallpaper> wallpapers)
        {
            panThumbnails.Controls.Clear();

            foreach (var wallpaper in wallpapers)
            {
                string lowerExtension = wallpaper.Extension.ToLower();
                if (AVAILABLE_FILE_EXTENSIONS.Contains(lowerExtension))
                {
                    var imageStream = new MemoryStream(wallpaper.File);
                    AddThumbnailToPanel(imageStream);
                }
            }
        }

        private void AddThumbnailToPanel(MemoryStream imageStream)
        {
            var wrapper = new Panel
            {
                Size = _thumbnailsSize,
                Padding = THUMBNAIL_FRAME_SIZE
            };
            var imgWallpaper = new PictureBox
            {
                Dock = DockStyle.Fill,
                Image = Image.FromStream(imageStream),
                SizeMode = PictureBoxSizeMode.Zoom
            };

            imgWallpaper.MouseEnter += (sender, args) => ChangePreview(((PictureBox)sender).Image);
            imgWallpaper.MouseDown += (sender, args) =>
            {
                if (SelectedPictureBox != null)
                {
                    SelectedPictureBox.Parent.BackColor = THUMBNAIL_BACK_COLOR;
                }
                var senderPictureBox = ((PictureBox) sender);
                if (senderPictureBox == SelectedPictureBox)
                {
                    SelectedPictureBox = null;
                    return;
                }

                SelectedPictureBox = senderPictureBox;
                SelectedPictureBox.Parent.BackColor = SELECTED_THUMBNAIL_BACK_COLOR;
            };
            imgWallpaper.MouseLeave += (sender, args) => ChangePreview(SelectedPictureBox != null ? SelectedPictureBox.Image : null);

            wrapper.Controls.Add(imgWallpaper);
            panThumbnails.Controls.Add(wrapper);
        }

        private void ChangePreview(Image image)
        {
            imgPreview.Image = image;
        }

        private void ChangeCategory(int id)
        {
            IList<Wallpaper> wallpapers = _wallpaperDao.SelectByCategoryId(id);

            AddThumbnailsToPanel(wallpapers);

            _selectedCategoryId = id;
        }

        private void ResizeThumbnails()
        {
            foreach (Control control in panThumbnails.Controls)
            {
                control.Size = _thumbnailsSize;
            }
        }

        private void OpenSaveFileDialog()
        {
            _saveFileDialog.FileName = DEFAULT_FILE_NAME;
            if (_saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                imgPreview.Image.Save(_saveFileDialog.FileName);
            }
        }


        private void LoadCategories()
        {
            IList<Category> categories = _categoryDao.SelectAll();
            mnuCategories.DropDownItems.Clear();

            foreach (var category in categories.OrderBy(x => x.Name))
            {
                var menuItem = new ToolStripMenuItem
                {
                    Text = category.Name,
                    Tag = category
                };

                menuItem.MouseUp += CategoryMenuItem_MouseUp;

                mnuCategories.DropDownItems.Add(menuItem);
            }

            SelectDefaultCategory();
        }

        private void CategoryMenuItem_MouseUp(object sender, MouseEventArgs e)
        {
            var menuItem = (ToolStripMenuItem)sender;
            if (menuItem.Checked)
            {
                return;
            }

            foreach (ToolStripMenuItem dropDownItem in mnuCategories.DropDownItems)
            {
                dropDownItem.Checked = false;
            }
            menuItem.Checked = true;

            var category = (Category) menuItem.Tag;
            ChangeCategory(category.Id);
        }

        private void SelectDefaultCategory()
        {
            var items = mnuCategories.DropDownItems;

            if (items.Count > 0)
            {
                var firstItem = (ToolStripMenuItem) items[0];
                CategoryMenuItem_MouseUp(firstItem, null);
            }
            else
            {
                panThumbnails.Controls.Clear();
            }
        }


        #region Events

        private void btnSave_Click(object sender, EventArgs e)
        {
            OpenSaveFileDialog();
        }

        private void ThumbnailsSize_Click(object sender, EventArgs e)
        {
            var button = (ToolStripButton)sender;
            int index;
            bool success = Int32.TryParse(button.Tag.ToString(), out index);
            if (success == false || index >= AVAILABLE_THUMBNAILS_SIZES.Count)
            {
                index = 0;
            }

            _thumbnailsSize = AVAILABLE_THUMBNAILS_SIZES[index];
            ResizeThumbnails();
        }

        private void mnuAddWallpaper_Click(object sender, EventArgs e)
        {
            var addWallpaperForm = new AddWallpaperForm();
            addWallpaperForm.WallpaperAdded += categoriesIds =>
            {
                if (categoriesIds.Contains(_selectedCategoryId))
                {
                    ChangeCategory(_selectedCategoryId);
                }
            };
            addWallpaperForm.ShowDialog();
        }

        #endregion


    }
}
